package com.putao.web.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.putao.annotation.OperateMethodName;
import com.putao.constants.Constants;
import com.putao.domain.Bill;
import com.putao.domain.Category;
import com.putao.result.JsonResult;
import com.putao.service.AccountBookService;
import com.putao.service.BillService;
import com.putao.service.CategoryService;
import com.putao.utils.BigDecimalUtil;
import com.putao.utils.ReflexUtil;
import com.putao.vo.BaseVo;
import com.putao.web.controller.vo.chart.BarVo;
import com.putao.web.controller.vo.chart.ChartVo;
import com.putao.web.controller.vo.chart.LineVo;
import com.putao.web.controller.vo.chart.PieVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author fuhehuang
 * @email 2628279194@qq.com
 */
@Api(tags = {"13.0 账单增删改查类"})
@RestController
@RequestMapping("/charts")
@Slf4j
public class ChartController {

    @Autowired
    private AccountBookService accountBookService;
    @Autowired
    private BillService billService;
    @Autowired
    private CategoryService categoryService;

    /**
     * 移动端图表数据
     *
     * @return
     */
    @GetMapping
    @ApiOperation(value = "移动端图表数据", notes = "移动端图表数据")
    @OperateMethodName(value = "移动端图表数据", method = "chart:chart")
    public JsonResult charts(BaseVo baseVo) throws Exception {
        if (ObjectUtil.isEmpty(baseVo.getParentId())) {
            return JsonResult.selectNotFound(null, null);
        }
        ChartVo chartVo = new ChartVo();
        List<Bill> billList = billService.getBillByAccountBookIdAndYearAndMonth(baseVo.getParentId(), baseVo.getYear(), baseVo.getMonth());
        if (CollectionUtil.isNotEmpty(billList)) {
            // 按照天进行统计，统计两个集合。当不存在数据时设置为0
            Set<Integer> dayStrSet = billList.stream().map(bill -> Integer.parseInt(bill.getDayStr())).collect(Collectors.toSet());
            Map<Integer, List<Bill>> dayBillListMap = billList.stream().collect(Collectors.groupingBy(bill -> Integer.parseInt(bill.getDayStr())));
            List<LineVo> lineVoList = new ArrayList<>();
            LineVo payLineVo = new LineVo();
            payLineVo.setName("支出");
            payLineVo.getColorByName();
            LineVo incomeLineVo = new LineVo();
            incomeLineVo.setName("收入");
            incomeLineVo.getColorByName();
            lineVoList.add(payLineVo);
            lineVoList.add(incomeLineVo);
            List<BigDecimal> payData = new ArrayList<>();
            payLineVo.setData(payData);
            List<BigDecimal> incomeData = new ArrayList<>();
            incomeLineVo.setData(incomeData);
            for (Integer day : dayStrSet) {
                List<Bill> bills = dayBillListMap.get(day);
                if (CollectionUtil.isEmpty(bills)) {
                    continue;
                }
                // 分类型统计
                Map<String, BigDecimal> typeMoneyMap = bills.stream().collect(Collectors.toMap(Bill::getType, Bill::getMoney, BigDecimal::add));
                BigDecimal payBigDecimal = typeMoneyMap.get(Constants.BILL_TYPE_PAY);
                BigDecimal incomeBigDecimal = typeMoneyMap.get(Constants.BILL_TYPE_INCOME);
                payData.add(null == payBigDecimal ? BigDecimal.ZERO : payBigDecimal);
                incomeData.add(null == incomeBigDecimal ? BigDecimal.ZERO : incomeBigDecimal);
            }
            chartVo.setLineXSet(dayStrSet);
            chartVo.setLineVoList(lineVoList);
        }
        // 预算
        List<Category> categoryList = categoryService.getForPayTypeByAccountBookId(baseVo.getParentId());
        Calendar instance = Calendar.getInstance();
        List<Category> budgetCategoryList = categoryList.stream().filter(category -> {
            instance.setTime(category.getCreateTime());
            return baseVo.getMonth().equals((instance.get(Calendar.MONTH) + 1) + "");
        }).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(budgetCategoryList)) {
            chartVo.setCategoryList(budgetCategoryList);
        }
        categoryList = categoryList.stream().filter(category -> {
            instance.setTime(category.getCreateTime());
            return BigDecimalUtil.biggerThen(category.getBalance(), BigDecimal.ZERO) && baseVo.getMonth().equals((instance.get(Calendar.MONTH) + 1) + "");
        }).sorted(Comparator.comparingInt(category -> category.getBalance().intValue())).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(categoryList)) {
            categoryList.forEach(category -> category.setRatio(category.getBalance().divide(category.getBudget(), RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)) + "%"));
        }
        if (CollectionUtil.isNotEmpty(categoryList) && categoryList.size() >= 5) {
            // 将分类数据转为饼图数据
            this.getPieByCategory(categoryList.subList(0, 4), chartVo);
        }
        if (ReflexUtil.checkEmpty(chartVo, ChartVo.ignoreColumnList)) {
            return JsonResult.selectNotFound(null, null);
        }
        return JsonResult.selectSuccess(chartVo, 0);
    }

    /**
     * 将分类数据转为饼图数据、横向柱形图
     * @param categoryList 分类数据
     * @param chartVo 返回结果
     */
    private void getPieByCategory(List<Category> categoryList, ChartVo chartVo) {
        List<PieVo> pieVoList = new ArrayList<>();
        List<BarVo> barVoList = new ArrayList<>();
        BigDecimal totalNum = categoryList.stream().map(Category::getBalance).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        for (Category category : categoryList) {

            PieVo pieVo = new PieVo();
            pieVo.setName(category.getName());
            pieVo.setValue(category.getBalance());
            pieVoList.add(pieVo);

            BarVo barVo = new BarVo();
            barVo.setName(category.getName());
            barVo.setBackground(category.getBgcColor());
            barVo.setNum(category.getBalance());
            barVo.setTotalNum(category.getBudget());
            barVo.setRatio(barVo.getNum().divide(totalNum, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)) + "%");
            barVoList.add(barVo);
        }
        chartVo.setPieVoList(pieVoList);
        chartVo.setBarVoList(barVoList);
    }

}
